// TestingProject.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <iterator>

#define BOOST_TEST_MODULE mytest

#include <algorithm>
#include <boost/test/unit_test.hpp>
#include "../P2pSystem/P2pSystem/Peer/Peer.h"
#include "../P2pSystem/P2pSystem/VectorTimer/FixedVectorTimer.h"



using std::cin;
using namespace Network::Peer;

/*
------------------------------------------------------------------------------------------------------
\\following this link
http://www.boost.org/doc/libs/1_51_0/libs/test/doc/html/tutorials/hello-the-testing-world.html
------------------------------------------------------------------------------------------------------

*/

//BOOST_AUTO_TEST_CASE(universeinorder)
//{
//	int a = 4;
//	int b = 4;
//	BOOST_CHECK(a == 4 && b == 4);
//	BOOST_CHECK(add(2,2) == 5);
//	BOOST_CHECK(add(2, 2) == 4);
//
//	
//	//BOOST_CHECK--->continues on an error
//	//BOOST_REQUIRE--->throws an error
//	//BOOST_ERROR--->continues on error
//	//BOOST_CHECK_MESSAGE--->continues on error and produces a msg on screen
//	//BOOST_CHECK_EQUAL--->continues on error
//	
//	
//}

//#include "CoreClasses\RGBObject\RGBColor.h"
//
///*
//	--------------------------------------
//			Testing RGBColor Class
//	--------------------------------------
//*/
//BOOST_AUTO_TEST_CASE(TestingRgbcolor)
//{
//	RGBColor color = RGBColor(0, 0, 0);
//	BOOST_CHECK(color.r == 0 && color.g == 0 && color.b == 1);
//	
//}
//
//#include "CoreClasses\Point\Point3D\Point3D.h"
//
///*
//	--------------------------------------
//			Testing Vector Class
//	--------------------------------------
//*/
//BOOST_AUTO_TEST_CASE(TestingVector)
//{
//	Point3D vectorTest = Point3D();
//	BOOST_CHECK_EQUAL(vectorTest != 0, false);
//
//	vectorTest = Point3D(0, 0, 0) + Point3D(1, 1, 1);
//
//
//	
//	
//}

/*
--------------------------------------
Testing Sampler
--------------------------------------
*/


BOOST_AUTO_TEST_CASE(TestingSampler)
{
	//Vector3D vector = Vector3D();
	//BOOST_CHECK(vector.x == 0 && vector.y == 0 && vector.z == 0 );

}

/*
--------------------------------------
Testing Peer neighbour handling
--------------------------------------
*/

BOOST_AUTO_TEST_CASE(TestingPeerClass)
{
	Network::Peer::Peer *testingPeer = new Peer("rtt");
	std::string inputNeighbours = "11223-127.0.0.1|21112;112356-124.0.0.12|2115;11223-127.0.0.1|21112;";
	testingPeer->AddNewNeighbours(inputNeighbours);
	/*testing neighbours size == 2*/
	BOOST_CHECK(testingPeer->neighbors.size() == 2);
	std::string toFind = "127.0.0.1|21112";
	int loc = 0;
	BOOST_CHECK(testingPeer->FindNeighbour(RakNet::SystemAddress(toFind.c_str()), loc) == true);
	testingPeer->RemoveNeighbour(loc);
	BOOST_CHECK(testingPeer->FindNeighbour(RakNet::SystemAddress(toFind.c_str()), loc) == false);

	BOOST_CHECK(testingPeer->GetCurrentLogicalTime() == 0);
	testingPeer->IncrementLogicalTime();
	BOOST_CHECK(testingPeer->GetCurrentLogicalTime() == 1);


	Neighbour randomNeighbor;
	randomNeighbor = testingPeer->GetRandomNeighbour();
	//BOOST_CHECK(randomNeighbor.address != NULL);

	testingPeer->RemoveNeighbour("124.0.0.12|2115");
	BOOST_CHECK(testingPeer->FindNeighbour(RakNet::SystemAddress(string("124.0.0.12|2115").c_str()), loc) == false);

	inputNeighbours = "11223-127.0.0.1|21112;112356-124.0.0.12|2115;11223-127.0.0.1|21112;114545-129.0.0.2|45669;1129-189.168.2.1|44568;";
	testingPeer->AddNewNeighbours(inputNeighbours);
	//sort 
	for (int index = 0; index < testingPeer->neighbors.size(); index++)
	{
		testingPeer->neighbors[index].UpdateLogicalTime(index);
	}

	testingPeer->SortCache();

	int previous = 0, current = 0;

	for (int index = 0; index < testingPeer->neighbors.size(); index++)
	{
		previous = index == 0 ? 0 : testingPeer->neighbors[index - 1].lastConnection;
		current = testingPeer->neighbors[index].lastConnection;
		BOOST_CHECK(previous <= current);
	}

	std::string output[2];

}




BOOST_AUTO_TEST_CASE(TestingVectorTimer)
{
	//one observable event
	std::string inputString = "abc-1,0,0,0,0,0,0,0,0,0;";
	int indexPosition = 1;
	FixedVectorTimer<std::string> test(indexPosition);
	test.FromString(inputString);

	BOOST_CHECK_EQUAL(test.updateRepresented, "abc");

	std::string testOuptut = test.ToString();
	BOOST_CHECK_EQUAL(testOuptut, inputString);

	test.UpdatePeerTimer(5);
	BOOST_CHECK_EQUAL(test.ToString(), "abc-1,5,0,0,0,0,0,0,0,0;");

	std::string difficultInputString = "a-,,,,,,,,,,";
	test.FromString(difficultInputString);

	BOOST_CHECK_EQUAL(test.updateRepresented, "a");
	for (int index = 0; index < test.vectorTimer.size(); index++)
	{
		BOOST_CHECK_EQUAL(test.vectorTimer[index], 0);
	}

}


#include "PeerSimulator.h"
#include "DetermineUpdate.h"

BOOST_AUTO_TEST_CASE(TestingPeerSimulator)
{
	std::string firstInputString = "a-1,0,0,0,0,0,0,0,0,0;";
	std::string secondInputString = "b-0,1,0,0,0,0,0,0,0,0;";

	FixedVectorTimer<std::string> test;
	int testIndex = 5;
	PeerSimulator simulator(testIndex, firstInputString);
	test.FromString(secondInputString);
	simulator.MergeUpdates(test);

	BOOST_CHECK_EQUAL(simulator.updater.ToString(), "ab-1,1,0,0,0,0,0,0,0,0;");

}

//#include "BoundingBox.h"
//
//BOOST_AUTO_TEST_CASE(TestingBoundingBox)
//{
//	Engine::BoundingBox *boundingBox = new Engine::BoundingBox();
//	boundingBox->Expand(Point3D(5, 5, 5));
//	boundingBox->Expand(Point3D(0, 0, 0));
//	
//	Point3D o = Point3D(-1, -1, -1);
//	Point3D d = boundingBox->GetCentroid();
//	Ray testRay = Ray(o,d);
//	double t = INT_MAX;
//	double tMax = INT_MAX;
//	bool result = boundingBox->CheckIntersection(testRay, t, tMax);
//
//	BOOST_CHECK_EQUAL(result, true);
//}

//#include "Triangle.h"
//#include "TriangleVertex.h"
//
//using namespace Engine;
//BOOST_AUTO_TEST_CASE(TestingTrinagleClass)
//{
//	//need to test intersection with a triangle
//	Point3D point1(10, 32.8858643, 89.2217865);
//	Point3D point2(10, 24.9462795, 89.2217865);
//	Point3D point3(10, 25.2625332, 88.5665131);
//
//	TriangleVertex vertex1(point1);
//	TriangleVertex vertex2(point2);
//	TriangleVertex vertex3(point3);
//
//	Triangle* currentTriangle = new Triangle(vertex1, vertex2, vertex3);
//
//	Ray currentRay;
//	currentRay.o = Point3D(0,0,0);
//	currentRay.d = Point3D(10,27.6982269,89.0033569);
//
//	ShadeRec rec;
//	double tmin;
//	tmin = INT_MAX;
//	bool firstTestOutput = currentTriangle->hit(currentRay.o, currentRay.d, tmin, rec);
//	
//
//	BOOST_CHECK_EQUAL(true, firstTestOutput);
//
//	/*tmin = INT_MAX;
//	bool secondTestOutput = currentTriangle->NewTriangleHit(currentRay.o, currentRay.d, tmin, rec);
//	BOOST_CHECK_EQUAL(true, secondTestOutput);*/
//
//}


//#include "..\CoreClasses\Sampler\Sampler.h"
//#include "Jittered.h"
//#include "Point2D.h"
//
//BOOST_AUTO_TEST_CASE(TestingSampling)
//{
//Engine::Sampler* testSampler = new Engine::Jittered();

//cout << testSampler->GetNumSamples() << endl;
//testSampler->GenerateSamples();

//for (int index = 0; index < testSampler->GetNumSamples(); index++)
//{
//	Point2D currentSample = 
//	cout << (Point2D)testSampler->SampleUnitSquare()
//}

//}
//#include "Jittered.h"
//
//BOOST_AUTO_TEST_CASE(SamplingTest)
//{
//	Jittered * jitteredSampler = new Jittered(4, 4);
//
//	jitteredSampler->GenerateSamples();
//
//	for (int index = 0; index < 4 * 4; index ++)
//	{
//		Point2D currentSample = jitteredSampler->SampleUnitSquare();
//		cout << currentSample.x << "---" << currentSample.y << endl;
//	}
//
//	jitteredSampler->MapSamplesToHemisphere(10);
//
//	for (int index = 0; index < 4 * 4; index ++)
//	{
//		Point3D currentSample = jitteredSampler->SampleHemispherical();
//		cout << currentSample.x << "--" << currentSample.y << "--" << currentSample.z << endl;
//	}
//}
//
//#include "Octree.h"
//#include "Scene.h"
//#include "SceneFactory.h"
//#include "RadiancePoint.h"
//
//BOOST_AUTO_TEST_CASE(IrradianceCahceOctree)
//{
//
//	int sceneIndex = 2;
//	Engine::Scene * currentScene = SceneFactory().GetScene(sceneIndex);
//	Engine::Octree * currentOctree = new Octree(currentScene);
//
//	float rayLength = 1;
//
//	//added four points 
//	//octree splitted
//	Engine::RadiancePoint * test0Point = new RadiancePoint(Point3D(-100, -100, -100), rayLength);
//	Engine::RadiancePoint * test1Point = new RadiancePoint(Point3D(100,100,100), rayLength);
//	Engine::RadiancePoint * test2Point = new RadiancePoint(Point3D(50, -50, 10), rayLength);
//	Engine::RadiancePoint * test3Point = new RadiancePoint(Point3D(100, 10, 20), rayLength);
//	currentOctree->InsertPoint(test0Point);
//	currentOctree->InsertPoint(test1Point);
//	currentOctree->InsertPoint(test2Point);
//	currentOctree->InsertPoint(test3Point);
//	//checked ofr a specific point 
//	BOOST_CHECK_EQUAL(true, currentOctree->CheckIfExist(Point3D(100, 100, 100)));
//
//}
//
//#include "IrradianceCache.h"
//#include "TracerFactory.h"
//BOOST_AUTO_TEST_CASE(IrradianceCalculations)
//{
//	int sceneIndex = 2;
//	Tracer* testTracer = TracerFactory().GetTracer(2);
//	Engine::Scene * currentScene = SceneFactory().GetScene(sceneIndex);
//	IrradianceCache * irradianceCacheTest = new IrradianceCache(currentScene, testTracer);
//}
//
//
///*
//	Rules for barycentrix coordinates 
//	1--> alpha beta and gamma can never be grater than 1
//*/
//BOOST_AUTO_TEST_CASE(BarycentricTesting)
//{
//	Point3D point1(0,0,0);
//	Point3D point2(1,0,0);
//	Point3D point3(0,1,0);
//
//
//	Point3D intersectionPoint(0.3, 0.3, 0);
//
//	Engine::Triangle currentTriangle(point1, point2, point3);
//	Point3D barCoor = currentTriangle.GetBarycentricCoordinates(intersectionPoint, Point3D(0), Ray());
//
//	cout << barCoor.toString() << endl;
//	//barycentric coordinates 
//
//}


#include "CoreClasses\Basis\OrthonomalBasis.h"
#include "CoreClasses\Point\Point3D\Point3D.h"

BOOST_AUTO_TEST_CASE(OrthonomalBasisTests)
{
	Engine::OrthonomalBasis basis;
	basis.ProduceOrthonomalBasis(Engine::Point3D(0, 0, 1));
}

/*
--------------------------------------
ending
--------------------------------------
*/
BOOST_AUTO_TEST_CASE(TestingEnding)
{
	int test = 0;
	cin >> test;

}


